package com.xl.utils.util.qiniuyun.service.impl;

import com.alibaba.fastjson.JSON;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.xl.utils.util.qiniuyun.Constant.QiniuyunConstant;
import com.xl.utils.util.qiniuyun.service.IQiniuyunService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author xionglin
 * @date 2019/10/26 18:11
 * @Description 上传操作的具体实现
 */
@Slf4j
@Component
public class IQiniuyunServiceImpl implements IQiniuyunService {
    private UploadManager uploadManager;

    private BucketManager bucketManager;

    private Auth auth;

    private StringMap putPolicy;

    /**
     * 配置为huanan（华南区）
     * 华东  Region.huadong()
     * 华北  Region.huabei()
     * 华南  Region.huanan()
     * 北美  Region.beimei()
     * @return
     */
    private Configuration qiniuConfig(){
        return new Configuration(Region.huanan());
    }

    /**
     * 认证信息实例配置公钥和私钥
     * @return
     */
    public Auth auth() {
        return Auth.create(QiniuyunConstant.ACCESS_KEY,QiniuyunConstant.SECRET_KEY);
    }

    /**
     * 项目启动初始化属性putPolicy,uploadManager,bucketManager。。。。。
     */
    @PostConstruct
    private void init(){
        this.uploadManager = new UploadManager(qiniuConfig());
        this.bucketManager = new BucketManager(auth(), qiniuConfig());
        this.auth = auth();
        this.putPolicy = new StringMap();
        this.putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}");
    }

    @Override
    public Response uploadFile(File file, String fileName) throws QiniuException {
        Response response = this.uploadManager.put(file, fileName, getUploadTokenWithFileName(fileName));
        int retry = 0;
        while (response.needRetry() && retry < 3) {
            response = this.uploadManager.put(file, fileName, getUploadToken());
            retry++;
        }
        return response;
    }

    /**
     *
     * @param inputStream
     * @param fileName 上传文件保存的文件名
     * @return
     * @throws QiniuException
     */
    @Override
    public Response uploadFile(InputStream inputStream, String fileName) throws QiniuException {
        Response response = this.uploadManager.put(inputStream, fileName, getUploadToken(), null, null);
        int retry = 0;
        while (response.needRetry() && retry < 3) {
            response = this.uploadManager.put(inputStream, fileName, getUploadToken(), null, null);
            retry++;
        }
        return response;
    }


    /**
     * MultipartFile上传
     * @param multipartFile
     * @return 文件地址
     * @throws QiniuException
     */
    @Override
    public String uploadFile(MultipartFile multipartFile) throws QiniuException {
        if(multipartFile == null || multipartFile.isEmpty()){
            return "file is empty";
        }
        InputStream inputStream = null;
        try {
            inputStream = multipartFile.getInputStream();
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        Response response = this.uploadFile(inputStream, multipartFile.getOriginalFilename());
        return getUrlByResponse(response);
    }

    /**
     * MultipartFile上传
     * @param multipartFile
     * @param onlyUrl true：返回的就是文件的地址   false：返回的是七牛的Response的响应体
     * @return 文件地址或响应体的json字符串
     * @throws QiniuException
     */
    @Override
    public String uploadFile(MultipartFile multipartFile,boolean onlyUrl) throws QiniuException {
        String result = "";
        if(multipartFile == null || multipartFile.isEmpty()){
            return "file is empty";
        }
        InputStream inputStream = null;
        try {
            inputStream = multipartFile.getInputStream();
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        Response response = this.uploadFile(inputStream, multipartFile.getOriginalFilename());
        result = onlyUrl ? getUrlByResponse(response):response.bodyString();
        return result;
    }

    /**
     * 删除指定资源。如果资源不存在，则返回错误码612
     * @param key 文件名称
     * @return
     * @throws QiniuException
     */
    @Override
    public Response delete(String key) throws QiniuException {
        Response response = bucketManager.delete(QiniuyunConstant.BUCKET_NAME, key);
        int retry = 0;
        while (response.needRetry() && retry++ < 3) {
            response = bucketManager.delete(QiniuyunConstant.BUCKET_NAME, key);
        }
        return response;
    }

    /**
     * 获取上传凭证
     *
     * @return
     */
    private String getUploadTokenWithFileName(String fileName) {
        return this.auth.uploadToken(QiniuyunConstant.BUCKET_NAME,fileName,QiniuyunConstant.EXPIRE_SECONDS,putPolicy);
    }

    /**
     * 获取上传凭证
     *
     * @return
     */
    private String getUploadToken() {
        return this.auth.uploadToken(QiniuyunConstant.BUCKET_NAME,null,QiniuyunConstant.EXPIRE_SECONDS,putPolicy);
    }

    /**
     * 根据Response解析出文件地址
     * @param response
     * @return
     * @throws QiniuException
     */
    private String getUrlByResponse(Response response) throws QiniuException {
        //ret:退回
        String retFileName = "";
        if(response != null && response.statusCode == 200){
            DefaultPutRet defaultPutRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
            if(defaultPutRet != null){
                retFileName = defaultPutRet.key;
            }
        }
        return QiniuyunConstant.PATH + "/" + retFileName;
    }

}
